package org.libcsp.retrofit2.autoconfigure;

import lombok.extern.slf4j.Slf4j;
import org.libcsp.retrofit2.annotation.Retrofit2Client;
import org.libcsp.retrofit2.factorybean.Retrofit2FactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.lang.NonNull;

import java.util.Objects;
import java.util.Set;

@SuppressWarnings({"FieldCanBeLocal","unused"})
@Slf4j
public class ClassPathRetrofit2ClientScanner extends ClassPathBeanDefinitionScanner {
    private final ClassLoader classLoader;

    public ClassPathRetrofit2ClientScanner(BeanDefinitionRegistry registry, ClassLoader classLoader) {
        super(registry,false);
        this.classLoader = classLoader;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        super.setResourceLoader(resourceLoader);
    }

    @Override
    @NonNull
    protected Set<BeanDefinitionHolder> doScan(@NonNull String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        processBeanDefinitions(beanDefinitions);
        return beanDefinitions;
    }

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        AnnotationMetadata metadata = beanDefinition.getMetadata();
        return metadata.isInterface();
    }
    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
        GenericBeanDefinition beanDefinition;
        for (BeanDefinitionHolder definitionHolder : beanDefinitions) {
            beanDefinition = (GenericBeanDefinition) definitionHolder.getBeanDefinition();
            log.info("创建RetrofitClientBean: {}",beanDefinition.getBeanClassName());
            beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(Objects.requireNonNull(beanDefinition.getBeanClassName()));
            beanDefinition.setBeanClass(Retrofit2FactoryBean.class);
        }
    }

    public void registryFilters() {
        AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(Retrofit2Client.class);
        this.addIncludeFilter(annotationTypeFilter);
    }

    public ClassLoader getClassLoader() {
        return classLoader;
    }
}
